home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / glibc108.zip / glibc108 / sunrpc / portmap.c < prev    next >
C/C++ Source or Header  |  1994-01-21  |  11KB  |  482 lines

  1. /* @(#)portmap.c    2.3 88/08/11 4.0 RPCSRC */
  2. #ifndef lint
  3. static    char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
  4. #endif
  5.  
  6. /*
  7.  * Copyright (c) 1984 by Sun Microsystems, Inc.
  8.  */
  9.  
  10. /*
  11.  * portmap.c, Implements the program,version to port number mapping for
  12.  * rpc.
  13.  */
  14.  
  15. /*
  16.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  17.  * unrestricted use provided that this legend is included on all tape
  18.  * media and as a part of the software program in whole or part.  Users
  19.  * may copy or modify Sun RPC without charge, but are not authorized
  20.  * to license or distribute it to anyone else except as part of a product or
  21.  * program developed by the user.
  22.  * 
  23.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  24.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  25.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  26.  * 
  27.  * Sun RPC is provided with no support and without any obligation on the
  28.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  29.  * modification or enhancement.
  30.  * 
  31.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  32.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  33.  * OR ANY PART THEREOF.
  34.  * 
  35.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  36.  * or profits or other special, indirect and consequential damages, even if
  37.  * Sun has been advised of the possibility of such damages.
  38.  * 
  39.  * Sun Microsystems, Inc.
  40.  * 2550 Garcia Avenue
  41.  * Mountain View, California  94043
  42.  */
  43.  
  44. #include <rpc/rpc.h>
  45. #include <rpc/pmap_prot.h>
  46. #include <stdio.h>
  47. #include <netdb.h>
  48. #include <sys/socket.h>
  49. #include <sys/ioctl.h>
  50. #include <sys/wait.h>
  51. #include <sys/signal.h>
  52.  
  53. char *malloc();
  54. int reg_service();
  55. void reap();
  56. struct pmaplist *pmaplist;
  57. static int debugging = 0;
  58.  
  59. main()
  60. {
  61.     SVCXPRT *xprt;
  62.     int sock, pid, t;
  63.     struct sockaddr_in addr;
  64.     int len = sizeof(struct sockaddr_in);
  65.     register struct pmaplist *pml;
  66.  
  67. #ifndef DEBUG
  68.     pid = fork();
  69.     if (pid < 0) {
  70.         perror("portmap: fork");
  71.         exit(1);
  72.     }
  73.     if (pid != 0)
  74.         exit(0);
  75.     for (t = 0; t < 20; t++)
  76.         close(t);
  77.      open("/", 0);
  78.      dup2(0, 1);
  79.      dup2(0, 2);
  80.      t = open("/dev/tty", 2);
  81.      if (t >= 0) {
  82.          ioctl(t, TIOCNOTTY, (char *)0);
  83.          close(t);
  84.      }
  85. #endif
  86.     if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  87.         perror("portmap cannot create socket");
  88.         exit(1);
  89.     }
  90.  
  91.     addr.sin_addr.s_addr = 0;
  92.     addr.sin_family = AF_INET;
  93.     addr.sin_port = htons(PMAPPORT);
  94.     if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
  95.         perror("portmap cannot bind");
  96.         exit(1);
  97.     }
  98.  
  99.     if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
  100.         fprintf(stderr, "couldn't do udp_create\n");
  101.         exit(1);
  102.     }
  103.     /* make an entry for ourself */
  104.     pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
  105.     pml->pml_next = 0;
  106.     pml->pml_map.pm_prog = PMAPPROG;
  107.     pml->pml_map.pm_vers = PMAPVERS;
  108.     pml->pml_map.pm_prot = IPPROTO_UDP;
  109.     pml->pml_map.pm_port = PMAPPORT;
  110.     pmaplist = pml;
  111.  
  112.     if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
  113.         perror("portmap cannot create socket");
  114.         exit(1);
  115.     }
  116.     if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
  117.         perror("portmap cannot bind");
  118.         exit(1);
  119.     }
  120.     if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
  121.         == (SVCXPRT *)NULL) {
  122.         fprintf(stderr, "couldn't do tcp_create\n");
  123.         exit(1);
  124.     }
  125.     /* make an entry for ourself */
  126.     pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
  127.     pml->pml_map.pm_prog = PMAPPROG;
  128.     pml->pml_map.pm_vers = PMAPVERS;
  129.     pml->pml_map.pm_prot = IPPROTO_TCP;
  130.     pml->pml_map.pm_port = PMAPPORT;
  131.     pml->pml_next = pmaplist;
  132.     pmaplist = pml;
  133.  
  134.     (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
  135.  
  136.     (void)signal(SIGCHLD, reap);
  137.     svc_run();
  138.     fprintf(stderr, "run_svc returned unexpectedly\n");
  139.     abort();
  140. }
  141.  
  142. static struct pmaplist *
  143. find_service(prog, vers, prot)
  144.     u_long prog;
  145.     u_long vers;
  146. {
  147.     register struct pmaplist *hit = NULL;
  148.     register struct pmaplist *pml;
  149.  
  150.     for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
  151.         if ((pml->pml_map.pm_prog != prog) ||
  152.             (pml->pml_map.pm_prot != prot))
  153.             continue;
  154.         hit = pml;
  155.         if (pml->pml_map.pm_vers == vers)
  156.             break;
  157.     }
  158.     return (hit);
  159. }
  160.  
  161. /* 
  162.  * 1 OK, 0 not
  163.  */
  164. reg_service(rqstp, xprt)
  165.     struct svc_req *rqstp;
  166.     SVCXPRT *xprt;
  167. {
  168.     struct pmap reg;
  169.     struct pmaplist *pml, *prevpml, *fnd;
  170.     int ans, port;
  171.     caddr_t t;
  172.     
  173. #ifdef DEBUG
  174.     fprintf(stderr, "server: about do a switch\n");
  175. #endif
  176.     switch (rqstp->rq_proc) {
  177.  
  178.     case PMAPPROC_NULL:
  179.         /*
  180.          * Null proc call
  181.          */
  182.         if ((!svc_sendreply(xprt, xdr_void, NULL)) && debugging) {
  183.             abort();
  184.         }
  185.         break;
  186.  
  187.     case PMAPPROC_SET:
  188.         /*
  189.          * Set a program,version to port mapping
  190.          */
  191.         if (!svc_getargs(xprt, xdr_pmap, ®))
  192.             svcerr_decode(xprt);
  193.         else {
  194.             /*
  195.              * check to see if already used
  196.              * find_service returns a hit even if
  197.              * the versions don't match, so check for it
  198.              */
  199.             fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
  200.             if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
  201.                 if (fnd->pml_map.pm_port == reg.pm_port) {
  202.                     ans = 1;
  203.                     goto done;
  204.                 }
  205.                 else {
  206.                     ans = 0;
  207.                     goto done;
  208.                 }
  209.             } else {
  210.                 /* 
  211.                  * add to END of list
  212.                  */
  213.                 pml = (struct pmaplist *)
  214.                     malloc((u_int)sizeof(struct pmaplist));
  215.                 pml->pml_map = reg;
  216.                 pml->pml_next = 0;
  217.                 if (pmaplist == 0) {
  218.                     pmaplist = pml;
  219.                 } else {
  220.                     for (fnd= pmaplist; fnd->pml_next != 0;
  221.                         fnd = fnd->pml_next);
  222.                     fnd->pml_next = pml;
  223.                 }
  224.                 ans = 1;
  225.             }
  226.         done:
  227.             if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
  228.                 debugging) {
  229.                 fprintf(stderr, "svc_sendreply\n");
  230.                 abort();
  231.             }
  232.         }
  233.         break;
  234.  
  235.     case PMAPPROC_UNSET:
  236.         /*
  237.          * Remove a program,version to port mapping.
  238.          */
  239.         if (!svc_getargs(xprt, xdr_pmap, ®))
  240.             svcerr_decode(xprt);
  241.         else {
  242.             ans = 0;
  243.             for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
  244.                 if ((pml->pml_map.pm_prog != reg.pm_prog) ||
  245.                     (pml->pml_map.pm_vers != reg.pm_vers)) {
  246.                     /* both pml & prevpml move forwards */
  247.                     prevpml = pml;
  248.                     pml = pml->pml_next;
  249.                     continue;
  250.                 }
  251.                 /* found it; pml moves forward, prevpml stays */
  252.                 ans = 1;
  253.                 t = (caddr_t)pml;
  254.                 pml = pml->pml_next;
  255.                 if (prevpml == NULL)
  256.                     pmaplist = pml;
  257.                 else
  258.                     prevpml->pml_next = pml;
  259.                 free(t);
  260.             }
  261.             if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
  262.                 debugging) {
  263.                 fprintf(stderr, "svc_sendreply\n");
  264.                 abort();
  265.             }
  266.         }
  267.         break;
  268.  
  269.     case PMAPPROC_GETPORT:
  270.         /*
  271.          * Lookup the mapping for a program,version and return its port
  272.          */
  273.         if (!svc_getargs(xprt, xdr_pmap, ®))
  274.             svcerr_decode(xprt);
  275.         else {
  276.             fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
  277.             if (fnd)
  278.                 port = fnd->pml_map.pm_port;
  279.             else
  280.                 port = 0;
  281.             if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
  282.                 debugging) {
  283.                 fprintf(stderr, "svc_sendreply\n");
  284.                 abort();
  285.             }
  286.         }
  287.         break;
  288.  
  289.     case PMAPPROC_DUMP:
  290.         /*
  291.          * Return the current set of mapped program,version
  292.          */
  293.         if (!svc_getargs(xprt, xdr_void, NULL))
  294.             svcerr_decode(xprt);
  295.         else {
  296.             if ((!svc_sendreply(xprt, xdr_pmaplist,
  297.                 (caddr_t)&pmaplist)) && debugging) {
  298.                 fprintf(stderr, "svc_sendreply\n");
  299.                 abort();
  300.             }
  301.         }
  302.         break;
  303.  
  304.     case PMAPPROC_CALLIT:
  305.         /*
  306.          * Calls a procedure on the local machine.  If the requested
  307.          * procedure is not registered this procedure does not return
  308.          * error information!!
  309.          * This procedure is only supported on rpc/udp and calls via 
  310.          * rpc/udp.  It passes null authentication parameters.
  311.          */
  312.         callit(rqstp, xprt);
  313.         break;
  314.  
  315.     default:
  316.         svcerr_noproc(xprt);
  317.         break;
  318.     }
  319. }
  320.  
  321.  
  322. /*
  323.  * Stuff for the rmtcall service
  324.  */
  325. #define ARGSIZE 9000
  326.  
  327. typedef struct encap_parms {
  328.     u_long arglen;
  329.     char *args;
  330. };
  331.  
  332. static bool_t
  333. xdr_encap_parms(xdrs, epp)
  334.     XDR *xdrs;
  335.     struct encap_parms *epp;
  336. {
  337.  
  338.     return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
  339. }
  340.  
  341. typedef struct rmtcallargs {
  342.     u_long    rmt_prog;
  343.     u_long    rmt_vers;
  344.     u_long    rmt_port;
  345.     u_long    rmt_proc;
  346.     struct encap_parms rmt_args;
  347. };
  348.  
  349. static bool_t
  350. xdr_rmtcall_args(xdrs, cap)
  351.     register XDR *xdrs;
  352.     register struct rmtcallargs *cap;
  353. {
  354.  
  355.     /* does not get a port number */
  356.     if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
  357.         xdr_u_long(xdrs, &(cap->rmt_vers)) &&
  358.         xdr_u_long(xdrs, &(cap->rmt_proc))) {
  359.         return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
  360.     }
  361.     return (FALSE);
  362. }
  363.  
  364. static bool_t
  365. xdr_rmtcall_result(xdrs, cap)
  366.     register XDR *xdrs;
  367.     register struct rmtcallargs *cap;
  368. {
  369.     if (xdr_u_long(xdrs, &(cap->rmt_port)))
  370.         return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
  371.     return (FALSE);
  372. }
  373.  
  374. /*
  375.  * only worries about the struct encap_parms part of struct rmtcallargs.
  376.  * The arglen must already be set!!
  377.  */
  378. static bool_t
  379. xdr_opaque_parms(xdrs, cap)
  380.     XDR *xdrs;
  381.     struct rmtcallargs *cap;
  382. {
  383.  
  384.     return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
  385. }
  386.  
  387. /*
  388.  * This routine finds and sets the length of incoming opaque paraters
  389.  * and then calls xdr_opaque_parms.
  390.  */
  391. static bool_t
  392. xdr_len_opaque_parms(xdrs, cap)
  393.     register XDR *xdrs;
  394.     struct rmtcallargs *cap;
  395. {
  396.     register u_int beginpos, lowpos, highpos, currpos, pos;
  397.  
  398.     beginpos = lowpos = pos = xdr_getpos(xdrs);
  399.     highpos = lowpos + ARGSIZE;
  400.     while ((int)(highpos - lowpos) >= 0) {
  401.         currpos = (lowpos + highpos) / 2;
  402.         if (xdr_setpos(xdrs, currpos)) {
  403.             pos = currpos;
  404.             lowpos = currpos + 1;
  405.         } else {
  406.             highpos = currpos - 1;
  407.         }
  408.     }
  409.     xdr_setpos(xdrs, beginpos);
  410.     cap->rmt_args.arglen = pos - beginpos;
  411.     return (xdr_opaque_parms(xdrs, cap));
  412. }
  413.  
  414. /*
  415.  * Call a remote procedure service
  416.  * This procedure is very quiet when things go wrong.
  417.  * The proc is written to support broadcast rpc.  In the broadcast case,
  418.  * a machine should shut-up instead of complain, less the requestor be
  419.  * overrun with complaints at the expense of not hearing a valid reply ...
  420.  *
  421.  * This now forks so that the program & process that it calls can call 
  422.  * back to the portmapper.
  423.  */
  424. static
  425. callit(rqstp, xprt)
  426.     struct svc_req *rqstp;
  427.     SVCXPRT *xprt;
  428. {
  429.     struct rmtcallargs a;
  430.     struct pmaplist *pml;
  431.     u_short port;
  432.     struct sockaddr_in me;
  433.     int pid, socket = -1;
  434.     CLIENT *client;
  435.     struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
  436.     struct timeval timeout;
  437.     char buf[ARGSIZE];
  438.  
  439.     timeout.tv_sec = 5;
  440.     timeout.tv_usec = 0;
  441.     a.rmt_args.args = buf;
  442.     if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
  443.         return;
  444.     if ((pml = find_service(a.rmt_prog, a.rmt_vers, IPPROTO_UDP)) == NULL)
  445.         return;
  446.     /*
  447.      * fork a child to do the work.  Parent immediately returns.
  448.      * Child exits upon completion.
  449.      */
  450.     if ((pid = fork()) != 0) {
  451.         if (debugging && (pid < 0)) {
  452.             fprintf(stderr, "portmap CALLIT: cannot fork.\n");
  453.         }
  454.         return;
  455.     }
  456.     port = pml->pml_map.pm_port;
  457.     get_myaddress(&me);
  458.     me.sin_port = htons(port);
  459.     client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &socket);
  460.     if (client != (CLIENT *)NULL) {
  461.         if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
  462.             client->cl_auth = authunix_create(au->aup_machname,
  463.                au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
  464.         }
  465.         a.rmt_port = (u_long)port;
  466.         if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
  467.             xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
  468.             svc_sendreply(xprt, xdr_rmtcall_result, &a);
  469.         }
  470.         AUTH_DESTROY(client->cl_auth);
  471.         clnt_destroy(client);
  472.     }
  473.     (void)close(socket);
  474.     exit(0);
  475. }
  476.  
  477. void
  478. reap()
  479. {
  480.     while (wait3(NULL, WNOHANG, NULL) > 0);
  481. }
  482.